#[cfg(test)]
mod tests {
    use crate::decimal_eval;

    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }

    #[test]
    fn test_eval() {
        let r = decimal_eval("0.1 + 0.2".to_string());
        println!("js = {:?}", r);

        let r = decimal_eval("decimal_eval('0.1 + 0.2')".to_string());
        println!("r = {:?}", r);

        let r = decimal_eval("let a = '0.1'; let b = '0.2'; decimal_eval(`${a} + ${b}`)".to_string());
        println!("r2 = {:?}", r);
    }
}

#[no_mangle]
pub fn test(msg: String) -> String {
    msg
}

#[no_mangle]
pub fn decimal_eval(js: String) -> Result<serde_json::Value, String> {
    use serde_v8::utils::v8_do;
    fn exec<'s>(
        scope: &mut v8::HandleScope<'s>,
        src: &str,
    ) -> Result<v8::Local<'s, v8::Value>, String> {
        let msg = || format!("执行代码有误: {{{}}}", src).to_string();
        let code = v8::String::new(scope, src).ok_or_else(msg)?;
        let script = v8::Script::compile(scope, code, None).ok_or_else(msg)?;
        let r = script.run(scope).ok_or_else(msg)?;
        Ok(r)
    }
    v8_do(|| {});
    let isolate = &mut v8::Isolate::new(v8::CreateParams::default());
    let handle_scope = &mut v8::HandleScope::new(isolate);
    let context = v8::Context::new(handle_scope);
    let scope = &mut v8::ContextScope::new(handle_scope, context);
    let index = include_str!("index.min.js");
    //evaluate('0.1 + 0.2')
    let v = exec(scope, &format!("{}; const decimal_eval = DecimalEval.evaluate;", index))?;
    serde_v8::from_v8::<serde_json::Value>(scope, v).map_err(|e| format!("初始化[DecimalEval]出错: {}", e.to_string()))?;
    let v = exec(scope, &js)?;
    let r = serde_v8::from_v8::<serde_json::Value>(scope, v).map_err(|e| e.to_string());
    r
}
